package com.duanjw.java.map;

/**
 * 自定义HashMap，数组+链表结构
 *
 * @author duanjw
 */
public class MyHashMyMap<K, V> implements MyMap<K, V> {
    private int size;
    Entry<K, V>[] table;

    public MyHashMyMap() {
        table = new Entry[16];
    }

    /**
     * key的hash的数组下标是否
     *
     * @param k
     * @param v
     * @return
     */
    @Override
    public V put(K k, V v) {
        int index = hash(k);
        Entry<K, V> kvEntry = table[index];
        if (kvEntry == null) {
            table[index] = new Entry<>(k, v, null, index);
            size++;
        } else {
            table[index] = new Entry<>(k, v, kvEntry, index);
        }
        return table[index].getValue();
    }

    /**
     * 计算hash值
     *
     * @param k
     * @return
     */
    private int hash(K k) {
        int hashCode = k.hashCode() % 16;
        return hashCode >= 0 ? hashCode : -hashCode;
    }

    /**
     * 根据key获取value
     *
     * @param k
     * @return
     */
    @Override
    public V get(K k) {
        int index = hash(k);
        Entry<K, V> kvEntry = table[index];
        if (size == 0 || kvEntry == null) {
            return null;
        }
        do {
            if (find(k, kvEntry) == null) {
                kvEntry = kvEntry.next;
            } else{
                return kvEntry.getValue();
            }
        } while (kvEntry != null);
return null;
//        return find(k, kvEntry);
    }

    /**
     * 如果传入的key等于当前对象的key，返回该对象
     * 如果传入的key不等于当前对象的key，迭代当前对象的链表，继续找符合的对象
     * 注意：由于此方法使用递归调用，所以此方法可能会有栈溢出的问题
     *
     * @param k
     * @param kvEntry
     * @return
     */
    private V find(K k, Entry<K, V> kvEntry) {
        if (k == kvEntry.getKey() || k.equals(kvEntry.getKey())) {
            return kvEntry.getValue();
        }
//        else {
//            while(kvEntry.next != null){
//                if (k == kvEntry.next.getKey() || k.equals(kvEntry.next.getKey())) {
//                    return kvEntry.getValue();
//                }
//            }
////            if (kvEntry.next != null) {
////                return find(k, kvEntry.next);
////            }
//        }
        return null;
    }

    @Override
    public int size() {
        return size;
    }

    class Entry<K, V> implements MyMap.Entry<K, V> {
        private K k;
        private V v;
        private Entry<K, V> next;
        private int hash;

        public Entry(K k, V v, Entry next, int hash) {
            this.k = k;
            this.v = v;
            this.next = next;
            this.hash = hash;
        }

        @Override
        public K getKey() {
            return k;
        }

        @Override
        public V getValue() {
            return v;
        }
    }
}
